package ifmo.compiler.task21.parser;

import ifmo.compiler.task21.lexer.Lexer;
import ifmo.compiler.task21.lexer.tokens.Token;
import ifmo.compiler.task21.lexer.tokens.TokenType;
import ifmo.compiler.task21.lexer.tokens.WrongTokenException;
import ifmo.compiler.task21.parser.symbols.*;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

public class TmpTester {

    public static Symbol[] getSymbols(String file, Task21Grammar grammar) throws Exception {
        List<Symbol> result = new ArrayList<Symbol>();

        Lexer lexer = new Lexer(new FileInputStream(file));
        Token token = null;
        do {
            try {
                token = lexer.nextToken();
                if (token == null) {
                    break;
                }
                Terminal t = grammar.FT(token.getType().toString());
                t.setLexval(String.valueOf(token.getValue()));

                result.add(t);
            } catch (WrongTokenException e) {
                System.out.println(e);
            }
        } while (token != null && token.getType() != TokenType.END);

        result.remove(result.size()-1);
        result.add(new EndSymbol());

        return result.toArray(new Symbol[result.size()]);
    }

	public static void main(String[] args) throws Exception {
		PredictiveAnalysTableCreater creator = new PredictiveAnalysTableCreater();
		Task21Grammar grammar = Task21Grammar.getInsctance();
		Production[] prod = new Production[0];
		Terminal[] terms = new Terminal[0];
		Nonterminal[] nonterms = new Nonterminal[0];
		PredictiveAnalysTable table = creator.create(grammar._productions
				.toArray(prod), grammar._terminals.toArray(terms),
				grammar._nonterminals.toArray(nonterms));

		PredictiveAnalisator analisator = new PredictiveAnalisator();

		try {

			Symbol[] w = getSymbols("examples/Example2.java", grammar);

			ArrayList<String> res = analisator.analys(w, table, grammar
					.FN("prog"));
			for (String s : res) {
				System.out.print(s);
			}
		} catch (Exception e) {
            System.out.println(e);
		}

        //Test1();
	}

	public static void Test1() throws Exception {
		ArrayList<Production> grammar = new ArrayList<Production>();
		Nonterminal E = new Nonterminal("E");
		Nonterminal E0 = new Nonterminal("E'");
		Nonterminal T = new Nonterminal("T");
		Nonterminal T0 = new Nonterminal("T'");
		Nonterminal F = new Nonterminal("F");

		Nonterminal[] nonterminals = { E, E0, T, T0, F };
		Terminal Plus = new Terminal("+");
		Terminal Mult = new Terminal("*");
		Terminal Left = new Terminal("(");
		Terminal Right = new Terminal(")");
		Terminal Id = new Terminal("id");

		Terminal[] terminals = { Plus, Mult, Left, Right, Id };
		OperationSymbol OPlus = new OperationSymbol("{+}");
		OperationSymbol OMult = new OperationSymbol("{*}");
		OperationSymbol OId = new OperationSymbol("{id}");

		E.MarkAsStartSymbol();

		{
			Symbol[] tail = { T, E0 };
			grammar.add(new Production(E, tail));
		}

		{
			Symbol[] tail = { Plus, T, OPlus, E0 };
			grammar.add(new Production(E0, tail, true));
		}

		{
			Symbol[] tail = { new Epsilon() };
			grammar.add(new Production(E0, tail));
			grammar.add(new Production(T0, tail));
			grammar.add(new Production(OPlus, tail, true));
			grammar.add(new Production(OMult, tail, true));
			grammar.add(new Production(OId, tail, true));
		}

		{
			Symbol[] tail = { F, T0 };
			grammar.add(new Production(T, tail));
		}

		{
			Symbol[] tail = { Mult, F, OMult, T0 };
			grammar.add(new Production(T0, tail, true));
		}

		{
			Symbol[] tail = { Left, E, Right };
			grammar.add(new Production(F, tail));
		}

		{
			Symbol[] tail = { Id, OId };
			grammar.add(new Production(F, tail, true));
		}

		PredictiveAnalysTableCreater creator = new PredictiveAnalysTableCreater();

		Production[] prod = new Production[0];
		PredictiveAnalysTable table = creator.create(grammar.toArray(prod),
				terminals, nonterminals);

		PredictiveAnalisator analisator = new PredictiveAnalisator();

		Id.setLexval("1");
		Plus.setLexval("+");
		Mult.setLexval("-");
		Symbol[] w = { Id, Plus, Id, Plus, Id, Mult, Id,
				new EndSymbol() };
		try {
			ArrayList<String> res = analisator.analys(w, table, E);
			for (String str : res){
				System.out.print(str);
			}
		} catch (Exception e) {
            System.out.println(e);
        }
	}

}
